#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>

void *connect_thread_fun(void *arg);


const char *quit="quit";
int connfd_list[10];

int * get_connfd_list()
{
    return connfd_list;
}

int main(int argc, char *argv[])
{
    pthread_t thread_id;
    int connfd = 0;
    memset(connfd_list, -1, sizeof(connfd_list));
    unsigned short port = 8080;
    
    if(argc!=1)
    {
        perror("wrong agrument");
        exit(-1);
    }
    
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);

    if(sockfd<0)
    {
        perror("socket");
        exit(-1);
    }

    //ip address and port struct
    struct sockaddr_in ser_addr;
    bzero(&ser_addr, sizeof(ser_addr));
    ser_addr.sin_family=AF_INET; //ipv4
    ser_addr.sin_port= htons(port);
    ser_addr.sin_addr.s_addr= htonl(INADDR_ANY);  //ip address

    //bind
    int err_log =bind(sockfd,
                      (struct sockaddr*)&ser_addr,
                      sizeof(ser_addr));
    if(err_log!=0)
    {
        perror("binding error");
        close(sockfd);
        exit(-1);
    }
    //listen
    err_log = listen(sockfd, 10);
    if(err_log!=0)
    {
        perror("listen error");

    }

    printf("waiting client @port=%d\n",port);
    
    while(1)
    {
        char client_ip[INET_ADDRSTRLEN]="";  //store  client ip 
        struct sockaddr_in client_addr;    //store client address
        socklen_t cliaddr_len= sizeof(client_addr); //initial

        //stop for the request
        connfd = accept(sockfd, (struct sockaddr*)&client_addr, &cliaddr_len);
        if(connfd<0)
        {
            perror("fail to accept");
            continue;
        }

        //print client's ip and port
        inet_ntop(AF_INET, &client_addr.sin_addr, client_ip, INET_ADDRSTRLEN);
        printf("a new client connected,ip:%s,port:%d\n", client_ip, ntohs(client_addr.sin_port));
        
        
        pthread_create(&thread_id, NULL, connect_thread_fun, (void *)&connfd);
       // pthread_detach(thread_id);
        
    }


    close(sockfd);


    
    return 0;
}


void *connect_thread_fun(void *arg)
{
    pthread_detach(pthread_self());
        
    int j;
    char temp[32]={""};
    char recv_buf[1024]={""};
    int this_connfd =*((int *)arg);
    int * list=get_connfd_list();

    for(j=0; j<10; j++)
    {
        if(*(list+j)<0)
        {
            *(list+j)=this_connfd;
            break;
        }else continue;
    }

    while(1)
    {

    bzero(temp, sizeof(temp));
    bzero(recv_buf,sizeof(recv_buf));

    if(recv(this_connfd, recv_buf, sizeof(recv_buf), 0)<=0)
    {
        break;
    }
    
    strncpy(temp, (recv_buf+strlen(recv_buf)-5), 4);

    if(strcmp(temp, quit)==0)
    {
       *(list+j)=-1;
       printf("quit");
       break;
      // close(connfd);
      // pthread_exit(0);
      // return NULL;

    }

    for(int i=0; i<10; i++)
    {
        if(*(list+i)>=0)
        {
            send(*(list+i), recv_buf, sizeof(recv_buf), 0);

        }
    }

    }

    close(this_connfd);

    pthread_exit(NULL);

    //return NULL;
    


}

